package com.chenyue.cm.api.login;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chenyue.cm.auth.Login;
import com.chenyue.cm.auth.LoginUser;
import com.chenyue.cm.bean.Success;
import com.chenyue.cm.common.constant.ErrorCode;
import com.chenyue.cm.common.utils.StringUtils;
import com.chenyue.cm.exception.SysRuntimeException;
import com.chenyue.cm.live.im.service.ImService;
import com.chenyue.cm.live.service.JdLiveService;
import com.chenyue.cm.user.domain.JdAppUser;
import com.chenyue.cm.user.domain.JdUserInvite;
import com.chenyue.cm.user.domain.vo.LoginInfo;
import com.chenyue.cm.user.service.JdAppUserService;
import com.chenyue.cm.user.service.JdUserInviteService;
import com.chenyue.cm.utils.MD5Util;
import com.chenyue.cm.utils.RedisUtils;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.io.IOException;
import java.util.Calendar;
import java.util.Collections;

/**
 * @author libingxing
 */
@Api(value = "APP用户维护API", tags = "登录注册编辑……")
@ApiSort(1)
@RestController
@RequestMapping("/api")
public class ApiLoginController {

    private final JdAppUserService jdAppUserService;

    private final JdLiveService liveService;

    private final RedisUtils redisUtils;

    private final JdUserInviteService userInviteService;

    private final ImService imService;

    public ApiLoginController(JdAppUserService jdAppUserService, JdLiveService liveService, RedisUtils redisUtils, JdUserInviteService userInviteService, ImService imService) {
        this.jdAppUserService = jdAppUserService;
        this.liveService = liveService;
        this.redisUtils = redisUtils;
        this.userInviteService = userInviteService;
        this.imService = imService;
    }

    @GetMapping("/checkVerifyCode")
    @ApiOperation("验证码校验")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "验证码", name = "verifyCode", dataType = "string", required = true),
    })
    public Success<String> checkVerifyCode(
            String mobile, String verifyCode
    ) {
        String errorMsg = jdAppUserService.checkVerifyCode(mobile, verifyCode);
//        校验验证码
        if (StringUtils.isNotBlank(errorMsg)) {
            return Success.error(errorMsg);
        }
        return Success.success();
    }

    @GetMapping("/checkMobile")
    @ApiOperation("手机号校验")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
    })
    public Success<String> checkMobile(
            String mobile
    ) {
        if (StringUtils.isEmpty(mobile)) {
            return Success.error();
        }
        final JdAppUser one = jdAppUserService.lambdaQuery()
                .eq(JdAppUser::getMobile, mobile)
                .one();
        if (one == null) {
            return Success.error(ErrorCode.MOBILE_REGISTER_ALREADY.getMsg());
        }
        return Success.success();
    }

    @PostMapping("/register")
    @ApiOperation(value = "APP用户注册", notes = "用户注册")
    @ApiOperationSupport(order = 1)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "密码", name = "password", dataType = "string", required = true),
            @ApiImplicitParam(value = "验证码", name = "verifyCode", dataType = "string", required = true),
            @ApiImplicitParam(value = "系统型号 1安卓2ios", name = "deviceModel", dataType = "string"),
            @ApiImplicitParam(value = "设备型号", name = "mobileModel", dataType = "string"),
            @ApiImplicitParam(value = "app版本", name = "appVersion", dataType = "string"),
            @ApiImplicitParam(value = "邀请码", name = "inviteCode", dataType = "string", required = true)
    })
    public Success<LoginInfo> register(
            String mobile, String verifyCode, String password,
            String deviceModel, String mobileModel, String appVersion, String inviteCode
    ) throws IOException {
        String errorMsg = jdAppUserService.checkVerifyCode(mobile, verifyCode);
//        校验验证码
        if (StringUtils.isNotBlank(errorMsg)) {
            return Success.error(errorMsg);
        }
        if (StringUtils.isEmpty(password)) {
            password = mobile;
        }
        LoginInfo loginInfo = jdAppUserService.register(mobile, deviceModel, mobileModel, appVersion, password, "");
        if (loginInfo == null) {
            return Success.error("注册失败");
        }
        imService.accountImport(jdAppUserService.getById(loginInfo.getUserId()));
        loginInfo.setRole(Collections.singletonList(1));
        if (StringUtils.isNotBlank(inviteCode)) {
            jdAppUserService.update(
                    new LambdaUpdateWrapper<JdAppUser>()
                            .eq(JdAppUser::getId, loginInfo.getUserId())
                            .set(JdAppUser::getInviteCode, inviteCode)
            );
//            邀请码
            final JdUserInvite one = userInviteService.lambdaQuery()
                    .eq(JdUserInvite::getInviteCode, inviteCode).last(" limit 1").one();
            if (one.getReceiveUser() == null || !one.getReceiveUser().equals(loginInfo.getUserId())) {
                one.setReceiveUser(loginInfo.getUserId());
                userInviteService.save(one);
            } else {
                userInviteService.updateById(one);
            }
        }
        return Success.success(loginInfo);
    }

    @PostMapping("/apiLogin")
    @ApiOperation(value = "APP登录", notes = "APP登录")
    @ApiOperationSupport(order = 2)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "密码", name = "password", dataType = "string"),
            @ApiImplicitParam(value = "验证码", name = "verifyCode", dataType = "string"),
            @ApiImplicitParam(value = "系统型号 1安卓2ios", name = "deviceModel", dataType = "string"),
            @ApiImplicitParam(value = "设备型号", name = "mobileModel", dataType = "string"),
            @ApiImplicitParam(value = "app版本", name = "appVersion", dataType = "string"),

    })
    public Success<LoginInfo> apiLogin(
            String mobile, String password, String verifyCode,
            Integer deviceModel, String mobileModel, String appVersion
    ) {
        if (StringUtils.isEmpty(mobile)) {
            return Success.error("请输入手机号");
        }
        QueryWrapper<JdAppUser> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile", mobile).last("limit 1");
        JdAppUser user = jdAppUserService.getOne(wrapper);
        if (user == null) {
            return Success.error(ErrorCode.MOBILE_UN_REGISTER.getMsg());
        }
        LoginInfo loginInfo = null;
        if (StringUtils.isNotBlank(password)) {
//            有密码 走密码登录
            loginInfo = jdAppUserService.pwdLogin(mobile, password, user);
        }
        if (StringUtils.isNotBlank(verifyCode)) {
//            有验证码 走验证码登录
            loginInfo = jdAppUserService.codeLogin(mobile, verifyCode, user);
        }
        if (loginInfo != null) {
            loginInfo.setIsAnchor(liveService.isAnchor(Integer.valueOf(user.getId())));
            updateUserLoginInfo(deviceModel, mobileModel, appVersion, Integer.valueOf(user.getId()));
            return Success.success(loginInfo);
        }
        return Success.error();
    }

    private void updateUserLoginInfo(Integer deviceModel, String mobileModel, String appVersion, Integer userId) {
        JdAppUser user = jdAppUserService.lambdaQuery().eq(JdAppUser::getId, userId).one();
        user.setId(userId);
        user.setLastLoginTime(Calendar.getInstance().getTime());
        user.setDeviceModel(deviceModel);
        user.setMobileModel(mobileModel);
        user.setAppVersion(appVersion);
        jdAppUserService.updateById(user);
    }

    @PostMapping("/wxLogin")
    @ApiOperation(value = "APP微信登录", notes = "APP微信登录")
    @ApiOperationSupport(order = 3)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "微信UnionId", name = "wxUnionId", dataType = "string", required = true),
            @ApiImplicitParam(value = "qqUnionId", name = "qqUnionId", dataType = "string", required = true),
            @ApiImplicitParam(value = "appleId", name = "appleId", dataType = "string", required = true),
            @ApiImplicitParam(value = "微信/QQ头像", name = "wxHeadImg", dataType = "string", required = true),
            @ApiImplicitParam(value = "微信/QQ名称", name = "wxUsername", dataType = "string", required = true),
            @ApiImplicitParam(value = "系统型号 1安卓2ios", name = "deviceModel", dataType = "string"),
            @ApiImplicitParam(value = "设备型号", name = "mobileModel", dataType = "string"),
            @ApiImplicitParam(value = "app版本", name = "appVersion", dataType = "string")

    })
    public Success<LoginInfo> wxLogin(
            String wxUnionId, String qqUnionId, String appleId, String wxHeadImg, String wxUsername,
            Integer deviceModel, String mobileModel, String appVersion
    ) throws IOException {
        JdAppUser user = null;
        if (StringUtils.isNotBlank(wxUnionId)) {
            user = jdAppUserService.lambdaQuery().eq(JdAppUser::getWxUnionId, wxUnionId).one();
        }
        if (StringUtils.isNotBlank(qqUnionId)) {
            user = jdAppUserService.lambdaQuery().eq(JdAppUser::getQqUnionId, qqUnionId).one();
        }
        if (StringUtils.isNotBlank(appleId)) {
            user = jdAppUserService.lambdaQuery().eq(JdAppUser::getAppleId, appleId).one();
        }

        LoginInfo loginInfo = jdAppUserService.wxLogin(user, wxUnionId, qqUnionId, appleId, wxHeadImg, wxUsername);

        if (loginInfo == null) {
            return Success.error("参数缺失");
        }

        if (loginInfo.getRole() == null || loginInfo.getRole().size() == 0) {
            jdAppUserService.insertRole(loginInfo.getUserId());
            imService.accountImport(jdAppUserService.getById(loginInfo.getUserId()));
            loginInfo.setRole(Collections.singletonList(1));
        }

        loginInfo.setIsAnchor(liveService.isAnchor(loginInfo.getUserId()));

        updateUserLoginInfo(deviceModel, mobileModel, appVersion, loginInfo.getUserId());
        return Success.success(loginInfo);
    }

    @Login
    @PostMapping("/bindPhone")
    @ApiOperation(value = "绑定手机号", notes = "绑定手机号")
    @ApiOperationSupport(order = 4)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "验证码", name = "verifyCode", dataType = "string", required = true),
            @ApiImplicitParam(value = "绑定类型1qq2微信3appleId", name = "type", dataType = "string", required = true)
    })
    @Transactional(rollbackFor = Exception.class)
    public Success<LoginInfo> bindPhone(
            @ApiIgnore @LoginUser JdAppUser user,
            String mobile, String verifyCode, Integer type
    ) {
        QueryWrapper<JdAppUser> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile", mobile).last("limit 1");
        JdAppUser mobileUser = jdAppUserService.getOne(wrapper);

        String errorMsg = jdAppUserService.checkVerifyCode(mobile, verifyCode);
        if (StringUtils.isNotBlank(errorMsg)) {
            return Success.error(errorMsg);
        }

        if (mobileUser != null) {
            if (type == 1) {
                if (StringUtils.isNotBlank(mobileUser.getQqUnionId())) {
                    return Success.error(ErrorCode.PHONE_HAS_BEEN_BIND.getCode(), ErrorCode.PHONE_HAS_BEEN_BIND.getMsg());
                }
            }
            if (type == 2) {
                if (StringUtils.isNotBlank(mobileUser.getWxUnionId())) {
                    return Success.error(ErrorCode.PHONE_HAS_BEEN_BIND.getCode(), ErrorCode.PHONE_HAS_BEEN_BIND.getMsg());
                }
            }
            if (type == 3) {
                if (StringUtils.isNotBlank(mobileUser.getAppleId())) {
                    return Success.error(ErrorCode.PHONE_HAS_BEEN_BIND.getCode(), ErrorCode.PHONE_HAS_BEEN_BIND.getMsg());
                }
            }
            LoginInfo loginInfo = jdAppUserService.mergeUser(user, mobileUser, type);
            return Success.success(loginInfo);
        }

        user.setMobile(mobile);
        int success = jdAppUserService.updateByPrimaryKey(user);
        if (success == 0) {
            throw new SysRuntimeException("绑定失败");
        }
        redisUtils.updateUser(user);
        final LoginInfo loginInfo = new LoginInfo();
        loginInfo.setHasPwd(StringUtils.isNotBlank(user.getPassword()) ? 1 : 2);
        return Success.success(loginInfo);
    }

    @PostMapping("/forgetPwd")
    @ApiOperation(value = "忘记密码", notes = "忘记密码")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "电话号码", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "验证码", name = "verifyCode", dataType = "string", required = true),
            @ApiImplicitParam(value = "新密码", name = "pwd", dataType = "string", required = true)
    })
    public Success<Object> forgetPwd(
            String mobile, String verifyCode, String pwd
    ) {
        String s = jdAppUserService.checkVerifyCode(mobile, verifyCode);
        if (StringUtils.isNotBlank(s)) {
            return Success.error(s);
        }
        Wrapper<JdAppUser> wrapper = new QueryWrapper<JdAppUser>().lambda()
                .eq(JdAppUser::getMobile, mobile).last("limit 1");
        JdAppUser one = jdAppUserService.getOne(wrapper);
        if (one == null) {
            return Success.error("用户不存在");
        }
        jdAppUserService.editPwd(Integer.valueOf(one.getId()), pwd);
        return Success.success();
    }

    @Login
    @PostMapping("/editPwd")
    @ApiOperation(value = "修改密码", notes = "修改密码")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "旧密码", name = "oldPwd", dataType = "string", required = true),
            @ApiImplicitParam(value = "新密码", name = "newPwd", dataType = "string", required = true)
    })
    public Success<Object> editPwd(
            @ApiIgnore @LoginUser JdAppUser user,
            String oldPwd, String newPwd
    ) {
        String salt = user.getSalt();
        String originPwd = MD5Util.getMD5(oldPwd + salt, false, 32);
        if (!user.getPassword().equals(originPwd)) {
            return Success.error("旧密码错误");
        }
        jdAppUserService.editPwd(Integer.valueOf(user.getId()), newPwd);
        return Success.success();
    }

    @Login
    @PostMapping("/setPwd")
    @ApiOperation(value = "设置密码", notes = "设置密码")
    @ApiOperationSupport(order = 7)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "新密码", name = "newPwd", dataType = "string", required = true)
    })
    public Success<Object> setPwd(
            @ApiIgnore @LoginUser JdAppUser user, String newPwd
    ) {
        jdAppUserService.editPwd(Integer.valueOf(user.getId()), newPwd);
        return Success.success();
    }

    @Login
    @PostMapping("/userCancel")
    @ApiOperation("用户注销")
    @ApiOperationSupport(order = 8)
    public Success<Object> userCancel(
            @ApiIgnore @LoginUser JdAppUser user
    ) {
        jdAppUserService.userCancel(user);
        return Success.success();
    }

    public static void main(String[] args) {
//        lk123456
//        String salt = StringUtil.getSalt();
//        System.err.println(salt);
        String realPass = MD5Util.getMD5("lk123456789" + "a589152e14b84408a5f689ef597aa327", false, 32);
//        String pwd = MD5Util.getMD5("lk123456", false, 32);
        System.err.println(realPass);
        System.err.println("a24f360828b3d49ec46241d49b91b3f0");

    }

}

